import os
from typing import Dict, Optional, Tuple

from loguru import logger

from mdtool.wx_cache import WxCache
from mdtool.wx_client import WxClient

from .config_reader import Config
from .error_handler import ErrorHandler
from .markdown_document import MarkdownDocument
from .util import download_image_to_dir


class ImageProcessor:
    """Base class for image processing."""

    def __init__(self, wx_client: WxClient, wx_cache: WxCache, config: Config = None):
        """Initialize the ImageProcessor."""
        self.client = wx_client
        self.cache = wx_cache
        self.error_handler = ErrorHandler()
        self.config = config

    def _get_local_image_path(self, url_path: str, md_file_dir: str) -> str:
        """处理本地图片路径 - 新的简化逻辑

        Args:
            url_path: 图片路径（来自 Markdown 文件）
            md_file_dir: Markdown 文件所在目录

        Returns:
            图片的绝对路径
        """
        if os.path.isabs(url_path):
            return os.path.normpath(url_path)
        if url_path.startswith("http"):
            return url_path
        clean_path = url_path.lstrip("./")
        full_path = os.path.join(md_file_dir, clean_path)
        return os.path.normpath(full_path)

    def _get_remote_image_path(self, url: str) -> str:
        """处理远程图片下载"""
        if self.config is not None and hasattr(Config, "WEB_DOWNLOADED_DIR"):
            download_dir = self.config.get(Config.WEB_DOWNLOADED_DIR)
        else:
            raise ValueError("web_downloaded_dir is not configured")
        try:
            return download_image_to_dir(url, download_dir)
        except Exception as e:
            logger.error(f"Failed to download image {url} to {download_dir} \n\t {e}")
            raise

    def _process_single_image(
        self, image_ref, md_file_dir: str
    ) -> Tuple[str, str, str]:
        """处理单个图片，返回 (原始URL, media_id, media_url)"""
        if image_ref.url_in_text.startswith("http"):
            image_full_path = self._get_remote_image_path(image_ref.url_in_text)
        else:
            image_full_path = self._get_local_image_path(
                image_ref.url_in_text, md_file_dir
            )
        try:
            media_id, media_url = self._upload_image(image_full_path)
            if media_id is None or media_url is None:
                raise ValueError(f"Failed to upload image {image_ref.url_in_text}")
            self.cache.set(image_full_path, media_id, media_url)
            logger.debug(f"{image_ref.url_in_text} => {media_id} and {media_url}")
            return image_ref.url_in_text, media_id, media_url
        except Exception as e:
            raise e

    def _update_document_status(
        self, md_doc: MarkdownDocument, success: bool, uploaded_images: Dict = None
    ):
        """更新文档状态"""
        md_doc.web_images_downloaded = success
        md_doc.image_uploaded = success
        md_doc.uploaded_images = uploaded_images if success else {}

    def process_article_images(
        self, md_doc: MarkdownDocument
    ) -> Dict[str, Tuple[str, str]]:
        """处理文章中的所有图片"""
        try:
            image_refs = md_doc.get_image_references()
            logger.debug(f"Processing {len(image_refs)} images for {md_doc.abs_path}")

            uploaded_images = {}
            # 获取 Markdown 文件所在目录
            md_file_dir = os.path.dirname(md_doc.abs_path)

            for image_ref in image_refs:
                try:
                    url_in_text, media_id, media_url = self._process_single_image(
                        image_ref, md_file_dir
                    )
                    uploaded_images[url_in_text] = [media_id, media_url]
                except Exception as e:
                    logger.error(str(e))
                    self._update_document_status(md_doc, False)
                    return None

            self._update_document_status(md_doc, True, uploaded_images)
            return uploaded_images

        except Exception:
            logger.error("Error in ImageProcessor.process_article_images")
            self._update_document_status(md_doc, False)
            return None

    def _upload_image(self, image_path: str) -> Tuple[Optional[str], Optional[str]]:
        """上传单张图片"""
        cache_value = self.cache.get(image_path)
        if cache_value != []:
            logger.debug(cache_value)
            md5, media_id, media_url, local_url = cache_value
            logger.debug(
                f"image {image_path} found in cache with{media_id} and {media_url}"
            )
            return media_id, media_url
        logger.debug(f"uploading image {image_path}")
        try:
            media_id, media_url = self.client.upload_permanent_media(
                image_path, os.path.basename(image_path)
            )
        except Exception as e:
            logger.warning(f"upload image error:{image_path}=> {e}")
            raise Exception from e
        return media_id, media_url
